﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dominio;
using System.Data.Objects;
using Excepciones;
using Watcher;

namespace Servicios
{
    public class FileSystemElementServiceDataBaseImpl : GenericService<FileSystemElement>, IFileSystemElementService
    {

        private static FileSystemElementServiceDataBaseImpl instancia = new FileSystemElementServiceDataBaseImpl();
        //private FileSystemWatcherListener fsWatch = FileSystemWatcherListener.ObtenerInstancia();

        private FileSystemElementServiceDataBaseImpl() : base() { }

        public static FileSystemElementServiceDataBaseImpl ObtenerInstancia()
        {
            return instancia;
        }

        public IList<FileSystemElement> ObtenerHijos(int id)
        {
            FileSystemElement padre = this.ObtenerPorId(id);
            return padre.ObtenerHijos();
        }

        protected override ObjectSet<FileSystemElement> GetObjectSet(DominioContainer ctx)
        {
            return ctx.FileSystemElements;
        }

        public override void Registrar(FileSystemElement t)
        {
            using (DominioContainer ctx = Ctx)
            {
                try
                {
                    if (ctx.FileSystemElements.First(f => f.Nombre == t.Nombre && f.Ruta == t.Ruta) != null)
                    {
                        throw new DataBaseException("Ya existe el FileSystemElement en el sistema");
                    }
                }
                catch (InvalidOperationException ioe) { //Vacio 
                }
                base.Registrar(t);
              //  fsWatch.RegistrarFileSystem(t.Ruta + "/" + t.Nombre);
                //Agregamos tambien el indice en la carpeta de lucene.
                 IndexServiceLuceneImpl.ObtenerInstancia().AgregarIndice(t);
            }
        }


        public void Modificar(FileSystemElement fileSystemElement)
        {
            using (DominioContainer ctx = new DominioContainer())
            {
                FileSystemElement fse = null;
                try
                {
                    fse = ctx.FileSystemElements.First(f => f.Id == fileSystemElement.Id);
                }
                catch (Exception ex)
                {
                    throw new DataBaseException("FileSystemElement no existente en la base de datos.");
                }
                if (fse == null)
                {
                    throw new DataBaseException("No existe un file system element con id " + fileSystemElement.Id + " en la base de datos.");
                }
                fse.Fecha = fileSystemElement.Fecha;
                fse.Nombre = fileSystemElement.Nombre;
                fse.Ruta = fileSystemElement.Ruta;
                if (fileSystemElement is Archivo) {
                    //((Archivo)fse).Extension = ((Archivo)fileSystemElement).Extension;
                    ((Archivo)fse).Tamanio = ((Archivo)fileSystemElement).Tamanio;
                }

                ctx.SaveChanges();
                //Modificamos el indice en la carpeta de lucene.
                 IndexServiceLuceneImpl.ObtenerInstancia().ModificarIndice(fileSystemElement);
            }
        }

        public FileSystemElement ObtenerPorId(int id)
        {
            using (DominioContainer ctx = new DominioContainer())
            {
                try
                {
                    FileSystemElement fse = ctx.FileSystemElements.First(f => f.Id == id);
                    return fse;
                }
                catch (Exception ex)
                {
                    throw new DataBaseException();
                }
            }
        }


        public FileSystemElement ObtenerPorRuta(string ruta)
        {
            using (DominioContainer ctx = new DominioContainer())
            {
                try
                {
                    int pos=ruta.LastIndexOf("/");
                    string rutaDir=ruta.Substring(0,pos);
                    string nombre= ruta.Substring(pos+1);
                    FileSystemElement fse = ctx.FileSystemElements.First(f => f.Ruta == rutaDir && f.Nombre == nombre );
                    return fse;
                }
                catch (Exception ex)
                {
                    return null;
                    throw new DataBaseException();
                }
            }
        }

        private string ObtenerRutaDeCarpetaContenedora(string ruta) 
        {
            try
            {
                FileInfo di = new FileInfo(ruta);
                return di.Directory.FullName;
            }
            catch (IOException e) {
                return null;
            }
        }

        private string ObtenerNombreDesdeRuta(string ruta)
        {
            try
            {
                FileInfo fi = new FileInfo(ruta);
                return fi.Name;
            }
            catch (IOException e)
            {
                return null;
            }
        }

        public override void Borrar(FileSystemElement t)
        {
            using (Ctx)
            {
                List<FileSystemElement> hijos = (List<FileSystemElement>)t.ObtenerHijos();
                if (hijos!=null && hijos.Count > 0)
                {
                    foreach (FileSystemElement hijo in hijos)
                    {
                        base.Borrar(hijo);
                        //Borramos el indice en lucene.
                        IndexServiceLuceneImpl.ObtenerInstancia().BorrarIndice(hijo);
                    }
                }
                FileSystemElement elem = ObtenerPorId(t.Id);
                base.Borrar(elem);
                //Borramos el indice en lucene.
                IndexServiceLuceneImpl.ObtenerInstancia().BorrarIndice(t);
            }
        }

        public List<FileSystemElement> ObtenerDirectorios()
        {
            List<FileSystemElement> dirs = new List<FileSystemElement>();
            using (DominioContainer ctx = Ctx)
            {
                var query = from f in ctx.FileSystemElements
                            select f;
                foreach (FileSystemElement fe in query)
                {
                    if (!(fe is Archivo))
                        dirs.Add(fe);
                }
            }
            return dirs;
        }

    }
}
